
Public Class bytes
    Inherits memblock(Of Byte)

    Private Shared ReadOnly _empty As bytes = Nothing

    Shared Sub New()
        _empty = New bytes()
        _empty.size = 0
    End Sub

    Public Shared Function empty() As bytes
        Return Global.copy(_empty)
    End Function

    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub New(ByVal value As bytes)
        MyBase.New(+value)
    End Sub

    Public Sub New(ByVal value As Byte)
        MyBase.New(value)
    End Sub

    Public Sub New(ByVal value() As Byte)
        MyBase.New(value)
    End Sub

    Public Sub New(ByVal value() As Byte, ByVal index As Int32, ByVal length As Int32)
        MyBase.New(value, index, length)
    End Sub

    Public Overloads Shared Widening Operator CType(ByVal this As Byte) As bytes
        Return New bytes(this)
    End Operator

    Public Overloads Shared Widening Operator CType(ByVal this() As Byte) As bytes
        If this Is Nothing OrElse this.Length = 0 Then
            Return Nothing
        Else
            Return New bytes(this)
        End If
    End Operator

    Public Overloads Shared Operator +(ByVal left As bytes, ByVal right As bytes) As bytes
        Dim rtn As bytes = Nothing
        rtn = New bytes()
        rtn.append(left, right)

        Return rtn
    End Operator

#If RETIRED Then
    Public Shared Shadows Operator +(ByVal left As bytes, ByVal right() As Byte) As bytes
        Return left + New bytes(right)
    End Operator

    Public Shared Shadows Operator +(ByVal left() As Byte, ByVal right As bytes) As bytes
        Return New bytes(left) + right
    End Operator

    Public Shared Shadows Operator +(ByVal left As bytes, ByVal right As Byte) As bytes
        Return left + New bytes(right)
    End Operator

    Public Shared Shadows Operator +(ByVal left As Byte, ByVal right As bytes) As bytes
        Return New bytes(left) + right
    End Operator
#End If

    Public Overrides Function Clone() As Object
        'though isCloneable should test whether me is nothing, but i have caught several crashes on this situation
        Dim obj As bytes = Nothing
        If Not Me Is Nothing Then
            obj = New bytes(Me)
        End If

        Return obj
    End Function

    Private Class unittestActions
        Private Shared Sub rndbyte(ByRef b As Byte)
            b = rnd(0, maxUInt8 + 1, True)
        End Sub

        Private Shared Sub rndbytearray(ByRef b() As Byte)
            ReDim b(rnd(0, 1024, True))
            Dim i As Int64
            For i = 0 To b.Length() - 1
                rndbyte(b(i))
            Next
        End Sub

        Private Shared Sub rndbytes(ByRef b As bytes)
            If b Is Nothing Then
                b = New bytes()
            Else
                b.clear()
            End If
            b.size() = rnd(0, 1024, True)
            Dim i As Int64
            For i = 0 To b.size() - 1
                rndbyte(b(i))
            Next
        End Sub

        Private Shared Sub assertsame(ByVal bt As bytes, ByVal b As Byte)
            assert(Not bt Is Nothing, "bt is nothing.")
            assert(bt.size() = 1 AndAlso bt(0) = b, "bt.size()<>1 or bt(0)<>b.")
        End Sub

        Private Shared Sub assertsame(ByVal b As bytes, ByVal array() As Byte)
            assert((b Is Nothing) = (array Is Nothing), "(b is nothing) <> (array is nothing).")
            If b Is Nothing Then
                Return
            End If

            assert(b.size() = array.Length() _
                   , "Byte Array.length is not same as bytes.size()")
            Dim i As Int64
            For i = 0 To array.Length() - 1
                assert(b(i) = array(i), "found b(" + Convert.ToString(i) + ") is not the same as the one in array.")
            Next
        End Sub

        Private Shared Sub assertsame(ByVal b As bytes, ByVal b2 As bytes)
            assert(Not b Is Nothing AndAlso Not b2 Is Nothing, "b is nothing or b2 is nothing.")
            assert(b.size() = b2.size() _
                   , "b.size() is not same as b2.size()")
            Dim i As Int64
            For i = 0 To b.size() - 1
                assert(b(i) = b2(i), "found b(" + Convert.ToString(i) + ") is not the same as the one in b2.")
            Next
        End Sub

        Public Shared Sub newas()
            Dim bt As bytes = Nothing
            Dim b As Byte
            rndbyte(b)
            bt = b
            assertsame(bt, b)
            Dim array() As Byte = Nothing
            rndbytearray(array)
            bt = array
            assertsame(bt, array)

            Dim bt2 As bytes = Nothing
            rndbytes(bt)
            bt2 = bt
            assertsame(bt, bt2)
        End Sub

        Private Shared Sub convertFromByte(ByVal bt As bytes, ByVal b As Byte)
            assertsame(bt, b)
        End Sub

        Private Shared Sub convertFromByteArray(ByVal b As bytes, ByVal array() As Byte)
            assertsame(b, array)
        End Sub

        Private Shared Sub convertToByteArray(ByRef b As bytes, ByRef comp As bytes)
            If b Is Nothing Then
                b = New bytes
            Else
                b.clear()
            End If
            b.size() = rnd(0, 1024, True)
            rndbytes(b)
            comp = b
        End Sub

        Public Shared Sub conv()
            Dim b As Byte = rnd(0, maxUInt8 + 1, True)
            convertFromByte(b, b)
            Dim array() As Byte = Nothing
            convertFromByteArray(array, array)
            rndbytearray(array)
            convertFromByteArray(array, array)

            Dim bt As bytes = Nothing
            convertToByteArray(array, bt)
            assertsame(bt, array)
        End Sub

        Public Shared Sub append()
            Dim bt As bytes = Nothing
            Dim b As Byte

            rndbyte(b)
            bt += b
            assertsame(bt, b)

            Dim array() As Byte = Nothing
            rndbytearray(array)
            bt.clear()
            bt += array
            assertsame(bt, array)

            Dim bt2 As bytes = Nothing
            bt2 = array + bt
            Dim array2(array.Length() + bt.size() - 1) As Byte
            memcpy(array2, 0, array, 0, array.Length())
            memcpy(array2, array.Length(), +bt, 0, bt.size())
            assertsame(bt2, array2)

            bt2 = bt + array
            memcpy(array2, 0, +bt, 0, bt.size())
            memcpy(array2, bt.size(), array, 0, array.Length())
            assertsame(bt2, array2)
        End Sub
    End Class

    Public Shared Sub automaticalUnittest()
        raiseError("******** automatical bytes unitTest ********", errorHandle.errorType.application)

        unittestActions.newas()
        unittestActions.conv()
        unittestActions.append()

        raiseError("******** finish automatical unitTest *******", errorHandle.errorType.application)
    End Sub
End Class
